﻿////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// <copyright>Copyright 2008-2011 Andreas Huber Doenni</copyright>
// Distributed under the Microsoft Public License (Ms-PL).
// See accompanying file License.txt or copy at http://mews.codeplex.com/license.
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

namespace Mews.Text
{
    using System;
    using System.Text;

    /// <summary>Represents an identity encoding of Unicode characters.</summary>
    /// <remarks><para>As the name suggests, the identity encoding means that a <see cref="byte"/> value b is mapped to
    /// a <see cref="char"/> value c such that <c>(char) b == c</c> yields true for all possible values of b. On the
    /// desktop variant of the .NET framework, the encoding available through <c>Encoding.GetEncoding("iso-8859-1")</c>
    /// provides such an identity transformation. This encoding is typically absent on the compact framework, which is
    /// why this class came into being.</para>
    /// <para><b>Note</b>: This class does not attempt to implement the rather complex fallback logic implemented for
    /// "iso-8859-1" on the desktop variant of the .NET framework, see <see cref="GetBytes"/> for more information.
    /// </para>
    /// </remarks>
    /// <threadsafety static="true" instance="false"/>
    public sealed class IdentityEncoding : Encoding
    {
        /// <summary>Initializes a new instance of the <see cref="IdentityEncoding"/> class.</summary>
        public IdentityEncoding() : base(0x6faf)
        {
        }

        /// <summary>See <see cref="Encoding.GetMaxCharCount"/>.</summary>
        public sealed override int GetMaxCharCount(int byteCount)
        {
            return byteCount;
        }

        /// <summary>See <see cref="Encoding.GetMaxByteCount"/>.</summary>
        public sealed override int GetMaxByteCount(int charCount)
        {
            return charCount;
        }

        /// <summary>See <see cref="Encoding.GetChars(byte[], int, int, char[], int)"/>.</summary>
        public sealed override int GetChars(byte[] bytes, int byteIndex, int byteCount, char[] chars, int charIndex)
        {
            AssertValidRanges(bytes, byteIndex, chars, charIndex, byteCount, "byteCount");
            int pastEnd = byteIndex + byteCount;

            for (; byteIndex < pastEnd; ++byteIndex, ++charIndex)
            {
                chars[charIndex] = (char)bytes[byteIndex];
            }

            return byteCount;
        }

        /// <summary>See <see cref="Encoding.GetCharCount(byte[], int, int)"/>.</summary>
        public sealed override int GetCharCount(byte[] bytes, int index, int count)
        {
            BufferHelper.AssertValidRange(bytes, "bytes", index, "index", count, "count");
            return count;
        }

        /// <summary>See <see cref="Encoding.GetBytes(char[], int, int, byte[], int)"/>.</summary>
        /// <remarks>Characters with a code > 0xFF are encoded as '?'.</remarks>
        public sealed override int GetBytes(char[] chars, int charIndex, int charCount, byte[] bytes, int byteIndex)
        {
            AssertValidRanges(bytes, byteIndex, chars, charIndex, charCount, "charCount");
            int pastEnd = charIndex + charCount;

            for (; charIndex < pastEnd; ++charIndex, ++byteIndex)
            {
                char character = chars[charIndex];

                if (character > 0xFF)
                {
                    character = '?';
                }

                bytes[byteIndex] = (byte)character;
            }

            return charCount;
        }

        /// <summary>See <see cref="Encoding.GetByteCount(char[], int, int)"/>.</summary>
        public sealed override int GetByteCount(char[] chars, int index, int count)
        {
            BufferHelper.AssertValidRange(chars, "chars", index, "index", count, "count");
            return count;
        }

        private static void AssertValidRanges(
            byte[] bytes, int byteIndex, char[] chars, int charIndex, int count, string countName)
        {
            BufferHelper.AssertValidRange(bytes, "bytes", byteIndex, "byteIndex", count, countName);
            BufferHelper.AssertValidRange(chars, "chars", charIndex, "charIndex", count, countName);
        }
    }
}
